use dioxus::prelude::*;
use std::str::FromStr;
use table_print::Table;

fn get_base_frequency(base_name: char, tune_name: &str) -> String {
    let tune_frequency = dizi::compute_note_frequency(tune_name).unwrap();
    let frequency = dizi::compute_base_frequency(base_name, tune_frequency);
    format!("{:.1}", frequency)
}

pub fn app(cx: Scope<()>) -> Element {
    let base_name = use_state(&cx, || "5".to_string());
    let diameter = use_state(&cx, || String::new());
    let base_frequency = use_state(&cx, || get_base_frequency('5', "A"));
    let result = use_state(&cx, || String::new());
    cx.render(rsx! {
        h1 {"笛子开孔位置计算器"}
        div {
            style: "line-height: 1.8",
            div {
                "筒音做 ",
                select {
                    value: "{base_name}",
                    onchange: move |e| base_name.set(e.value.clone()),
                    option {
                        value: "5",
                        "5",
                    },
                    option {
                        value: "2",
                        "2",
                    },
                }
                " 1= ",
                select {
                    onchange: move |e| {
                        let base_name = base_name.chars().next().unwrap();
                        let tune_name = &e.value;
                        let frequency = get_base_frequency(base_name, tune_name);
                        base_frequency.set(frequency);
                    },
                    {dizi::NOTES.iter().map(|&note| rsx!{
                        option {
                            value: "{note}",
                            "{note}",
                        },
                    })}
                }
                "调"
            }
            div {
                "管径 ",
                input {
                    style: "width: 6em",
                    r#type: "number",
                    value: "{diameter}",
                    onchange: move |e| diameter.set(e.value.clone()),
                },
                "mm"
            }
            div {
                "基音频率 ",
                input {
                    style: "width: 6em",
                    r#type: "number",
                    value: "{base_frequency}",
                    onchange: move |e| base_frequency.set(e.value.clone()),
                },
                "Hz"
            }
            div {
                button {
                    style: "width: 6em; margin: 1em",
                    onclick: move |_| {
                        let base_name = base_name.chars().next().unwrap();
                        if let Ok(diameter) = f64::from_str(diameter) {
                            if let Ok( base_frequency) = f64::from_str(base_frequency){
                                let data = dizi::compute_lengths(
                                    base_name,
                                    diameter,
                                    base_frequency,
                                    None,
                                );
        
                                let mut table = Table::new(vec![]);
                                for row in data {
                                    table.insert_row(row);
                                }
                                let mut html = table.get_html_element();
                                html.push_str("<p>说明：等效长度是与声音频率对应的声学长度，等于基频声波的半个波长。<br />
                                由于端口和出音孔的影响，实际管长小于有效长度，数值为吹孔到出音孔之间的距离。</p>");
                                result.set(html);
                            } else {
                                result.set("基音频率必须填写数字".to_string());
                            }
                        } else {
                            result.set("管径必须填写数字".to_string());
                        }
                    },
                    "计算"
                }
            }
            div {
                dangerous_inner_html: "{result}"
            }
        }
    })
}

pub fn main() {
    dioxus::web::launch(app);
}
